package parsingvalues

import (
	"bytes"
	"encoding/binary"
	"encoding/json"
	"errors"
	"fmt"
	"math"
)

type ParseRequestData struct {
	FunctionCode uint8
	Data         []byte
	DataTypes    string   //数据类型 int16-2 uint16-2 int32-4 uint32-4 int64-8 uint64-8 float32-4 float64-8
	Key          []string //属性名（如：temp,hum等）
	ByteOrder    string   //字节序 big little
}

func (m *ParseRequestData) NewParseRequestData(functionCode uint8, data []byte, dataTypes string, key []string, byteOrder string) *ParseRequestData {
	m.FunctionCode = functionCode //功能码
	m.Data = data                 //数据
	m.DataTypes = dataTypes       //数据类型 int16-2 uint16-2 int32-4 uint32-4 int64-8 uint64-8 float32-4 float64-8
	m.Key = key                   //属性名（如：temp,hum等）
	m.ByteOrder = byteOrder       //字节序 big little
	return &ParseRequestData{}
}

func (m *ParseRequestData) ParseRequestData() ([]byte, error) {
	dataMap := make(map[string]interface{})

	// 检查 key 长度是否足够
	dataLength := map[string]int{
		"int":       1, // 一个字节
		"int16-2":   2,
		"uint16-2":  2,
		"int32-4":   4,
		"uint32-4":  4,
		"int64-8":   8,
		"uint64-8":  8,
		"float32-4": 4,
		"float64-8": 8,
	}
	length, ok := dataLength[m.DataTypes]
	if !ok {
		return nil, errors.New("unknown data type")
	}
	if len(m.Key)*length > len(m.Data) {
		return nil, errors.New("key length less than data length")
	}
	fmt.Println("数据位是：", m.Data)
	fmt.Println("数据类型是：", m.DataTypes)
	buf := bytes.NewReader(m.Data)
	for idx, key := range m.Key {
		switch m.DataTypes {
		case "int":
			var value byte
			err := binary.Read(buf, binary.BigEndian, &value) // 因为线圈数据只是一个字节，所以字节序不重要
			if err != nil {
				return nil, err
			}
			coilStatus := (value >> uint(7-idx)) & 0x01 // 从最高位开始读取
			dataMap[key] = int(coilStatus)
		case "int16-2":
			var value int16
			if m.ByteOrder == "big" {
				err := binary.Read(buf, binary.BigEndian, &value)
				if err != nil {
					return nil, err
				}
			} else {
				err := binary.Read(buf, binary.LittleEndian, &value)
				if err != nil {
					return nil, err
				}
			}
			dataMap[key] = value
		case "uint16-2":
			var value uint16
			if m.ByteOrder == "big" {
				err := binary.Read(buf, binary.BigEndian, &value)
				if err != nil {
					return nil, err
				}
			} else {
				err := binary.Read(buf, binary.LittleEndian, &value)
				if err != nil {
					return nil, err
				}
			}
			dataMap[key] = value
		case "int32-4":
			var value int32
			if m.ByteOrder == "big" {
				err := binary.Read(buf, binary.BigEndian, &value)
				if err != nil {
					return nil, err
				}
			} else {
				err := binary.Read(buf, binary.LittleEndian, &value)
				if err != nil {
					return nil, err
				}
			}
			dataMap[key] = value
		case "uint32-4":
			var value uint32
			if m.ByteOrder == "big" {
				err := binary.Read(buf, binary.BigEndian, &value)
				if err != nil {
					return nil, err
				}
			} else {
				err := binary.Read(buf, binary.LittleEndian, &value)
				if err != nil {
					return nil, err
				}
			}
			dataMap[key] = value
		case "float32-4":
			var value uint32
			if m.ByteOrder == "big" {
				err := binary.Read(buf, binary.BigEndian, &value)
				if err != nil {
					return nil, err
				}
			} else {
				err := binary.Read(buf, binary.LittleEndian, &value)
				if err != nil {
					return nil, err
				}
			}
			dataMap[key] = math.Float32frombits(value)
		case "int64-8":
			var value int64
			if m.ByteOrder == "big" {
				err := binary.Read(buf, binary.BigEndian, &value)
				if err != nil {
					return nil, err
				}
			} else {
				err := binary.Read(buf, binary.LittleEndian, &value)
				if err != nil {
					return nil, err
				}
			}
			dataMap[key] = value
		case "uint64-8":
			var value uint64
			if m.ByteOrder == "big" {
				err := binary.Read(buf, binary.BigEndian, &value)
				if err != nil {
					return nil, err
				}
			} else {
				err := binary.Read(buf, binary.LittleEndian, &value)
				if err != nil {
					return nil, err
				}
			}
			dataMap[key] = value

		case "float64-8":
			var value uint64
			if m.ByteOrder == "big" {
				err := binary.Read(buf, binary.BigEndian, &value)
				if err != nil {
					return nil, err
				}
			} else {
				err := binary.Read(buf, binary.LittleEndian, &value)
				if err != nil {
					return nil, err
				}
			}
			dataMap[key] = math.Float64frombits(value)
		}
	}

	jsonData, err := json.Marshal(dataMap)
	if err != nil {
		return nil, err
	}
	return jsonData, nil

}
